package com.lill.system.config;

import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import com.lill.system.constant.SystemConstant;
import com.lill.system.dao.ISysMenuDao;
import com.lill.system.dao.ISysUserDao;
import com.lill.system.model.SysMenuEntity;

/**
 * 分布式session管理
 *
 * @author lill
 */
//@Component("cluterShiroSessionDao")
public class CluterShiroSessionDao extends EnterpriseCacheSessionDAO {

	public static final String SESSION_KEY = SystemConstant.SYS_CACHE_SESSION+":SESSIONID_";
	protected Logger logger = LoggerFactory.getLogger(getClass());

	@Resource(name="commonRedisTemplate")
	private RedisTemplate<String, Session> redisTemplate;
	@Resource(name="commonRedisTemplate")
	private RedisTemplate<String, List<String>> redisMenuListTemplate;
	@Autowired(required=false)
	private ISysUserDao sysUserDao;
	@Autowired(required=false)
	private ISysMenuDao sysMenuDao;

	@Override
	protected Serializable doCreate(Session session) {
		Serializable sessionId = super.doCreate(session);
		final String key = SESSION_KEY + sessionId.toString();
		setShiroSession(key, session);
		return sessionId;
	}

	@Override
	protected Session doReadSession(Serializable sessionId) {
		Session session = super.doReadSession(sessionId);
		if (null == session) {
			final String key = SESSION_KEY + sessionId.toString();
			session = getShiroSession(key);
		}
		return session;
	}

	@Override
	protected void doUpdate(Session session) {
		super.doUpdate(session);
		final String key = SESSION_KEY + session.getId().toString();
		setShiroSession(key, session);
	}

	@Override
	protected void doDelete(Session session) {
		super.doDelete(session);
		final String key = SESSION_KEY + session.getId().toString();
		redisTemplate.delete(key);
	}

	private Session getShiroSession(String key) {
		Session session=redisTemplate.opsForValue().get(key);
		setShiroSession(key, session);
		return session;
	}

	private void setShiroSession(String key, Session session) {
		redisTemplate.opsForValue().set(key, session, SystemConstant.SYS_CACHE_SESSION_TIME, TimeUnit.SECONDS);
		try {
			if(null==session){
				return;
			}

			Collection<Object> sessionKeys=session.getAttributeKeys();
			if(sessionKeys.isEmpty()||!sessionKeys.contains(SystemConstant.CURRENT_USER)){
				return;
			}
			Object userObj=SecurityUtils.getSubject().getPrincipal();
//			try {
//				userObj= SecurityUtils.getSubject().getPrincipal();
//			} catch (Exception e) {
////				userObj=session.getAttribute(SystemConstant.CURRENT_USER);
//				logger.error(e.getMessage(),e);
//			}
			if(null!=userObj){
				String userId=new PropertyDescriptor("id", userObj.getClass()).getReadMethod().invoke(userObj).toString();
				String companyId=new PropertyDescriptor("companyId", userObj.getClass()).getReadMethod().invoke(userObj).toString();
				Object domainObj=new PropertyDescriptor("domainId", userObj.getClass()).getReadMethod().invoke(userObj);
				String domainId=null;
				if(null!=domainObj){
					domainId=domainObj.toString();
				}

				String permsKey=SystemConstant.SYS_PERMS_KEY+userId;

				if(redisMenuListTemplate.hasKey(SystemConstant.SYS_PERMS_KEY+userId)){
					redisTemplate.expire(permsKey, SystemConstant.SYS_CACHE_SESSION_TIME,TimeUnit.SECONDS);
					return;
				}
				List<String> permsList=null;
				//系统管理员，拥有最高权限
				if (SystemConstant.SUPER_ADMIN.equals(userId)) {
					Map<String, Object> adminParam=new HashMap<String, Object>();

					adminParam.put("domainId", domainId);
					List<SysMenuEntity> menuList = sysMenuDao.queryList(adminParam);
					permsList = new ArrayList<String>();
					for (SysMenuEntity menu : menuList) {
						if(StringUtils.isNotEmpty(menu.getPerms())){
							String[] perms=menu.getPerms().split(",");
							for (String permVal : perms) {
								permsList.add(permVal);
							}
						}
					}
				} else {
					Map<String, Object> userParam=new HashMap<String, Object>();
					userParam.put("userId", userId);
					userParam.put("companyId", companyId);
					userParam.put("domainId", domainId);
					List<SysMenuEntity> menuList=sysMenuDao.queryCurUserMenuList(userParam);
					permsList = new ArrayList<String>();
					if(null!=menuList&&!menuList.isEmpty()){
						for (SysMenuEntity menu : menuList) {
							if(StringUtils.isNotEmpty(menu.getPerms())){
								String[] perms=menu.getPerms().split(",");
								for (String permVal : perms) {
									permsList.add(permVal);
								}
							}

						}
					}
//    				permsList = sysUserDao.queryAllPerms(userId);
				}
				redisMenuListTemplate.opsForValue().set(permsKey, permsList, SystemConstant.SYS_CACHE_SESSION_TIME, TimeUnit.SECONDS);
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}
}
